package com.guos.redis;

import redis.clients.jedis.Jedis;

import java.util.Collections;

/**
 * 每一行代码，都是改变世界的力量
 *
 * @author 郭帅
 * @date 2022/6/30 10:41 下午
 */
public class RedisLock {

    /**
     * @param jedis      redis 客户端
     * @param lockKey    锁的标识
     * @param clientId   客户端的标识
     * @param expireTime 过期时间
     * @return true 表示获取成功，false，表示获取失败
     */
    public static boolean tryGetLock(Jedis jedis, String lockKey, String clientId, int expireTime) {
        return "OK".equals(jedis.set(lockKey, clientId, "NX", "EX", expireTime));
    }

    /**
     * @param jedis    redis 客户端
     * @param lockKey  锁的标识
     * @param clientId 客户端的标识
     * @return true 表示释放锁成功，false，表示释放锁失败
     */
    public static boolean releaseLock(Jedis jedis, String lockKey, String clientId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(clientId));
        return new Long(1L).equals(result);
    }

    public static boolean wrongGetLock1(Jedis jedis, String lockKey, String clientId, int expireTime) {
        Long setnx = jedis.setnx(lockKey, clientId);
        if (setnx > 1) {
            // 如果程序崩溃造成死锁
            jedis.expire(lockKey, expireTime);
            return true;
        }
        return false;
    }

    public static void wrongReleaseLock1(Jedis jedis, String lockKey) {
        // 可能导致任何客户端都可以对其解锁
        jedis.del(lockKey);
    }

    public static void wrongReleaseLock2(Jedis jedis, String lockKey, String clientId) {
        if (clientId.equals(jedis.get(lockKey))) {
            // 如果在del 时，锁过期了，被另一个客户端加锁，岂不是将另一个客户端的锁给解除了？
            jedis.del(lockKey);
        }
    }


    /**
     * https://juejin.cn/post/6844903507363905549
     */
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        if (tryGetLock(jedis, "mylock", "guos", 1)) {
            System.out.println(releaseLock(jedis, "mylock", "guos"));
        }
    }
}
